package com.cqc.jdk8.Jutil.concurrent;

import org.junit.Test;

import java.util.Collections;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;

/**
 * 多个任务组合处理
 * and组合、or组合、andOf、anyOf
 */
public class CompletableFuture2Test {

    @Test
    public void runAfterBoth() throws Exception {
        CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
            System.out.println("future1 runAsync");
            this.sleepSecond(1);
        });
        CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
            System.out.println("future2 runAsync");
            this.sleepSecond(1);
            //int a = 1 / 0;
        });
        //必须有get()，当future1 future2都正确完成，才会走 runAfterBoth
        future1.runAfterBoth(future2, () -> {
            System.out.println("runAfterBoth");
        }).get();
    }


    @Test
    public void thenAcceptBoth() throws Exception {
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            this.sleepSecond(1);
            System.out.println("future1 supplyAsync");
            return "future1 supplyAsync";
        });
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            this.sleepSecond(1);
            System.out.println("future2 supplyAsync");
            //int a = 1 / 0;
            return "future2 supplyAsync";
        });

        //BiConsumer 第1个参数是 future2的返回值。
        //必须有get()，当future1 future2都正确完成，才会走 thenAcceptBoth
        future1.thenAcceptBoth(future2, (future2Result, future1Result) -> {
            System.out.println(",future1Result:" + future1Result + ", future2Result:" + future2Result);
        }).get();
    }

    /**
     * 计算合并 thenCombine
     */
    @Test
    public void thenCombine() throws Exception {
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("future1");
            //int a = 1 / 0;
            return 1;
        });
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("future2");
            return "2";
        });
        //第2个参数的参数（x,y）x是future1的结果，y是future2的结果，
        //必须有get()，当future1 future2都正确完成，才会走 thenCombine
        String result = future1.thenCombine(future2, (x, y) -> x + y + "ABC").get();
        //相当于
//        String result = future1.thenCombine(future2,new BiFunction<Integer, String, String>() {
//
//            @Override
//            public String apply(Integer future1Result, String future2Result) {
//                return future1Result + "" + future2Result + "ABC";
//            }
//        }).get();
        System.out.println(result);
    }

    /**
     * 表示将两个CompletableFuture任务组合起来，只要其中一个正常执行完了，就会继续执行回调任务
     */
    @Test
    public void runAfterEither() throws Exception {
        CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
            this.sleepSecond(1);
            System.out.println("future1 runAsync");
        });
        CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
            this.sleepSecond(2);
            System.out.println("future2 runAsync");
            //int a = 1 / 0;
        });
        //必须有get()，当future1 future2都正确完成，才会走 runAfterBoth。
        CompletableFuture<Void> future = future1.runAfterEither(future2, () -> {
            System.out.println("runAfterEither");
        });
        future.get();
        //顺序
//        future1 runAsync
//        runAfterEither
    }

    /**
     * 表示将两个CompletableFuture任务组合起来，只要其中一个正常执行完了，就会继续执行回调任务
     */
    @Test
    public void acceptEither() throws Exception {
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            this.sleepSecond(1);
            System.out.println("future1 supplyAsync");
            //int a = 1 / 0;
            return "future1 supplyAsync";
        });
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            this.sleepSecond(2);
            System.out.println("future2 supplyAsync");
            return "future2 supplyAsync";
        });
        //必须有get()，当future1 future2都正确完成，才会走 runAfterBoth。
        future1.acceptEither(future2, (firstResult) -> {
            System.out.println("firstResult:" + firstResult);
        }).get();
    }


    /**
     * 执行顺序：
     * future1 supplyAsync
     * future2 supplyAsync
     * 所有任务都执行成功，result:null
     * allOf
     */
    @Test
    public void allOf() throws Exception {
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            this.sleepSecond(1);
            System.out.println("future1 supplyAsync");
            //int a = 1 / 0;
            return "future1 supplyAsync";
        });
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            this.sleepSecond(2);
            System.out.println("future2 supplyAsync");
            return "future2 supplyAsync";
        });
        //必须有get()，当future1 future2都正确完成，才会走 runAfterBoth。
        String result = CompletableFuture.allOf(future1, future2)
                .thenApply(x -> x)//x是null，
                .handle((r, e) -> {
                    System.out.println("所有任务都执行成功，result:" + r);
                    return "allOf";
                })
                .get();
        System.out.println(result);
    }


    @Test
    public void anyOf() throws Exception {
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            this.sleepSecond(1);
            System.out.println("future1 supplyAsync");
            //int a = 1 / 0;
            return "future1 supplyAsync";
        });
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            this.sleepSecond(2);
            System.out.println("future2 supplyAsync");
            return "future2 supplyAsync";
        });
        CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {
            this.sleepSecond(2);
            System.out.println("future3 supplyAsync");
            return "future3 supplyAsync";
        });
        //必须有get()，当future1 future2都正确完成，才会走 runAfterBoth。
        CompletableFuture<String> future = CompletableFuture.anyOf(new CompletableFuture[]{future1, future2, future3})
                .thenApply(x -> x)//x是null，
                .handle((r, e) -> {
                    System.out.println("其中一个执行成功，result:" + r);
                    return "anyOf";
                });
        String result = future.get();
        System.out.println(result);
    }

    private void sleepSecond(int timeout) {
        try {
            TimeUnit.SECONDS.sleep(timeout);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}


